#include "stdafx.h"
#include "ImageTGA.h"

//-------------------------------------------------------------------------
// constructors
//-------------------------------------------------------------------------

CImageTGA::CImageTGA()
{
	m_pTGAFileHeader = NULL;
	m_pImageData = NULL;
};

//-------------------------------------------------------------------------
// destructors
//-------------------------------------------------------------------------

CImageTGA::~CImageTGA()
{
	if (m_pTGAFileHeader != NULL) 
	{
		delete m_pTGAFileHeader;
		m_pTGAFileHeader = NULL;
	}

	if (m_pImageData != NULL) 
	{
		delete m_pImageData;
		m_pImageData = NULL;
	}
};

//-------------------------------------------------------------------------
// member functions
//-------------------------------------------------------------------------

int CImageTGA::Load(CString path)
{

	// Open the file

	CFile tgafile;
	if (!tgafile.Open(path, CFile::modeRead | CFile::shareExclusive))
	{
		return(-1);
	}

	// Dump out old info

	if (m_pTGAFileHeader != NULL) 
	{
		delete m_pTGAFileHeader;
		m_pTGAFileHeader = NULL;
	}

	if (m_pImageData != NULL) 
	{
		delete m_pImageData;
		m_pImageData = NULL;
	}

	// Read in the header

	m_pTGAFileHeader = new TGAFileHeader;
	tgafile.Read(m_pTGAFileHeader, sizeof(TGAFileHeader));

	// Check image type and make sure it is one of the supported types:
	// (2) uncompressed true-color
	// (3) uncompressed black-and-white

	if (m_pTGAFileHeader->ImageType < 2 || m_pTGAFileHeader->ImageType > 3) return(-2);

	// Check for possible Image ID data

	if (m_pTGAFileHeader->IDLength > 0) // then skip over to image data
	{
		tgafile.Seek((LONG)m_pTGAFileHeader->IDLength, CFile::current);
	}

	// Use pixel depth to calculate the number of information bytes per pixel.
	// There are width*height # of pixels...

	m_nBytesPerPixel = m_pTGAFileHeader->Image.PixelDepth / 8;
	m_nTotalImageBytes = m_nBytesPerPixel * m_pTGAFileHeader->Image.Width * m_pTGAFileHeader->Image.Height;

	// Read in the image data

	m_pImageData = new unsigned char[m_nTotalImageBytes];
	tgafile.Read(m_pImageData, m_nTotalImageBytes);

	// TGA files store pixel data in the BGR(A) format, so we need to swap the 
	// B and R bytes to conform to OpenGL's RGB(A) format if the pixel depth is
	// 24 or 32.

	if (m_nBytesPerPixel > 2)
	{
		unsigned char BlueByte;
		for (int i=0; i<m_nTotalImageBytes; i+= m_nBytesPerPixel) 
		{
			BlueByte = m_pImageData[i];
			m_pImageData[i] = m_pImageData[i+2];
			m_pImageData[i+2] = BlueByte;
		}
	}

	// Close the file

	tgafile.Close();

return(1);
}

//-------------------------------------------------------------------------

void CImageTGA::ConvertRGBToGreyscale(float RedWeightFactor, float GreenWeightFactor, float BlueWeightFactor)
{
	// Check to see if it already is greyscale

	if (m_nBytesPerPixel < 2) return;

	// Create a new array to store the converted bytes

	m_nTotalImageBytes = sizeof(unsigned char) * m_pTGAFileHeader->Image.Width * m_pTGAFileHeader->Image.Height;
	unsigned char *pConvertedImageData;
	pConvertedImageData = new unsigned char[m_nTotalImageBytes];

	// Convert the image bytes to greyscale using the supplied weighting factors

	int i=0;
	for (int j=0; j < m_nTotalImageBytes; j++, i += m_nBytesPerPixel)
	{
		pConvertedImageData[j] = (unsigned char) (RedWeightFactor * m_pImageData[i] +
												  GreenWeightFactor * m_pImageData[i+1] +
												  BlueWeightFactor * m_pImageData[i+2]);
	}

	// Delete old bytes and replace with new bytes

	delete m_pImageData;
	m_pImageData = pConvertedImageData;

	// Reset the TGAHeader to reflect new data bytes

	m_nBytesPerPixel = 1;
	m_pTGAFileHeader->Image.PixelDepth = 8;
	m_pTGAFileHeader->ImageType = 3;
}

//-------------------------------------------------------------------------

int CImageTGA::Save(CString path)
{
	// Make sure image data has already been loaded

	if (m_pTGAFileHeader == NULL) return (-1);
	if (m_pImageData == NULL) return (-2);

	// Open file for writing

	CFile tgafile;
	if (!tgafile.Open(path, CFile::modeWrite | CFile::modeCreate | CFile::shareExclusive))
	{
		return(-3);
	}

	// Write the header

	tgafile.Write(&m_pTGAFileHeader->IDLength, sizeof(unsigned char));
	tgafile.Write(&m_pTGAFileHeader->ColorMapType, sizeof(unsigned char));
	tgafile.Write(&m_pTGAFileHeader->ImageType, sizeof(unsigned char));

	tgafile.Write(&m_pTGAFileHeader->ColorMap.FirstEntryIndex, sizeof(unsigned short));
	tgafile.Write(&m_pTGAFileHeader->ColorMap.Length, sizeof(unsigned short));
	tgafile.Write(&m_pTGAFileHeader->ColorMap.Size, sizeof(unsigned char));

	tgafile.Write(&m_pTGAFileHeader->Image.XOrigin, sizeof(unsigned short));
	tgafile.Write(&m_pTGAFileHeader->Image.YOrigin, sizeof(unsigned short));
	tgafile.Write(&m_pTGAFileHeader->Image.Width, sizeof(unsigned short));
	tgafile.Write(&m_pTGAFileHeader->Image.Height, sizeof(unsigned short));
	tgafile.Write(&m_pTGAFileHeader->Image.PixelDepth, sizeof(unsigned char));
	tgafile.Write(&m_pTGAFileHeader->Image.Descriptor, sizeof(unsigned char));

	// TGA files store pixel data in the BGR(A) format, so we need to swap the 
	// B and R bytes from OpenGL's RGB(A) format if the pixel depth is
	// 24 or 32.

	if (m_nBytesPerPixel > 2)
	{
		unsigned char RedByte;
		for (int i=0; i<m_nTotalImageBytes; i+= m_nBytesPerPixel) 
		{
			RedByte = m_pImageData[i];
			m_pImageData[i] = m_pImageData[i+2];
			m_pImageData[i+2] = RedByte;
		}
	}

	// Write the image bytes

	tgafile.Write(m_pImageData, m_nTotalImageBytes);

return(0);
}

//-------------------------------------------------------------------------

void CImageTGA::SetupUncomp8Bit(int nSize)
{
	// Dump out old info

	if (m_pTGAFileHeader != NULL) 
	{
		delete m_pTGAFileHeader;
		m_pTGAFileHeader = NULL;
	}

	if (m_pImageData != NULL) 
	{
		delete m_pImageData;
		m_pImageData = NULL;
	}

	// Init the header info

	m_pTGAFileHeader = new TGAFileHeader;
	m_pTGAFileHeader->IDLength = 0;
	m_pTGAFileHeader->ColorMapType = 0;
	m_pTGAFileHeader->ImageType = 3;
	m_pTGAFileHeader->ColorMap.FirstEntryIndex = 0;
	m_pTGAFileHeader->ColorMap.Length = 0;
	m_pTGAFileHeader->ColorMap.Size = 0;
	m_pTGAFileHeader->Image.XOrigin = 0;
	m_pTGAFileHeader->Image.YOrigin = 0;
	m_pTGAFileHeader->Image.Width = nSize;
	m_pTGAFileHeader->Image.Height = nSize;
	m_pTGAFileHeader->Image.PixelDepth = 8;
	m_pTGAFileHeader->Image.Descriptor = 0;

	// Init member variables

	m_nBytesPerPixel = 1;
	m_nTotalImageBytes = m_nBytesPerPixel * nSize * nSize;
	m_pImageData = new unsigned char[m_nTotalImageBytes];
}

//-------------------------------------------------------------------------

void CImageTGA::SetupUncomp24Bit(int nSize)
{
	// Dump out old info

	if (m_pTGAFileHeader != NULL) 
	{
		delete m_pTGAFileHeader;
		m_pTGAFileHeader = NULL;
	}

	if (m_pImageData != NULL) 
	{
		delete m_pImageData;
		m_pImageData = NULL;
	}

	// Init the header info

	m_pTGAFileHeader = new TGAFileHeader;
	m_pTGAFileHeader->IDLength = 0;
	m_pTGAFileHeader->ColorMapType = 0;
	m_pTGAFileHeader->ImageType = 2;
	m_pTGAFileHeader->ColorMap.FirstEntryIndex = 0;
	m_pTGAFileHeader->ColorMap.Length = 0;
	m_pTGAFileHeader->ColorMap.Size = 0;
	m_pTGAFileHeader->Image.XOrigin = 0;
	m_pTGAFileHeader->Image.YOrigin = 0;
	m_pTGAFileHeader->Image.Width = nSize;
	m_pTGAFileHeader->Image.Height = nSize;
	m_pTGAFileHeader->Image.PixelDepth = 24;
	m_pTGAFileHeader->Image.Descriptor = 0;

	// Init member variables

	m_nBytesPerPixel = 3;
	m_nTotalImageBytes = m_nBytesPerPixel * nSize * nSize;
	m_pImageData = new unsigned char[m_nTotalImageBytes];
}